﻿# coding: utf-8

import string

import wx
import wx.lib.scrolledpanel as scrolled
import wx.lib.colourselect as csel

from wxFramework.CustomUI import wxColorPickButton

import Scene
import LightAmbient
import LightDirection
import MaterialStatic
import MPFog

class wxPanelPropertySceneLight(scrolled.ScrolledPanel):
    def __init__(self, parent, id):
        """ Default class constructor """
        
        scrolled.ScrolledPanel.__init__(self, parent, id)
        
        # Layout all UI.
        sizerAmbientLight = self.__CreateUIAmbientLight()
        sizerDirectionalLight = self.__CreateUIDirectionalLight()
        sizerFog = self.__CreateUIFog()

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(sizerAmbientLight, 0, wx.LEFT|wx.RIGHT|wx.EXPAND, border = 10)
        sizer.Add(sizerDirectionalLight, 0, wx.LEFT|wx.RIGHT|wx.EXPAND, border = 10)
        sizer.Add(sizerFog, 0, wx.LEFT|wx.RIGHT|wx.EXPAND, border = 10)
        self.SetSizer(sizer)
        
        # Bind all events.
        self._ambientColorButton.Bind(csel.EVT_COLOURSELECT, self.__OnAmbientColorChanged)
        self._editAmbientBrightness.Bind(wx.EVT_KILL_FOCUS, self.__OnAmbientLightBrightnessChanged)
        self._directionDiffuseColorButton.Bind(csel.EVT_COLOURSELECT, self.__OnDirectionDiffuseColorChanged)
        self._directionSpecularColorButton.Bind(csel.EVT_COLOURSELECT, self.__OnDirectionSpecularColorChanged)
        self._editDirectionLightBrightess.Bind(wx.EVT_KILL_FOCUS, self.__OnDirectionalLightBrightnessChanged)
        self._editDirection.Bind(wx.EVT_KILL_FOCUS, self.__OnDirectionalLightDirectionChanged)
        self._cbEnableFog.Bind(wx.EVT_CHECKBOX, self.__OnCbEnableFog)
        self._editFogStart.Bind(wx.EVT_KILL_FOCUS, self.__OnFogStartChanged)
        self._editFogStart.Bind(wx.EVT_KILL_FOCUS, self.__OnFogEndChanged)
        self._fogColorButton.Bind(csel.EVT_COLOURSELECT, self.__OnFogColorChanged)
        
    def __CreateUIAmbientLight(self):
        """ Create ambient light property UI """
        
        sbAmbientLight = wx.StaticBox(self, -1, TD.SCENE_AMBIENT_LIGHT)
        sizerAmbientLight = wx.StaticBoxSizer(sbAmbientLight, wx.VERTICAL)
        
        # Ambient light color.
        static = wx.StaticText(self, -1, TD.AMBIENT_LIGHT_COLOR)
        self._ambientColorButton = wxColorPickButton(self, -1, '')
        sizerAmbientLightColor = wx.BoxSizer(wx.HORIZONTAL)
        sizerAmbientLightColor.Add(static, 0, wx.CENTER, border = 0)
        sizerAmbientLightColor.Add(self._ambientColorButton, 0, wx.CENTER, border = 0)
        
        static = wx.StaticText(self, -1, TD.LIGHT_BRIGHTESS)
        self._editAmbientBrightness = wx.TextCtrl(self, -1, '')
        sizerBrightness = wx.BoxSizer(wx.HORIZONTAL)
        sizerBrightness.Add(static, 0, wx.CENTER, border = 0)
        sizerBrightness.Add(self._editAmbientBrightness, 0, wx.CENTER, border = 0)

        sizerAmbientLight.Add(sizerAmbientLightColor, 1, wx.EXPAND|wx.ALL, border = 5)
        sizerAmbientLight.Add(sizerBrightness, 1, wx.EXPAND|wx.ALL, border = 5)
        return sizerAmbientLight
        
    def __CreateUIDirectionalLight(self):
        """ Create directional light property UI """
        
        sbDirectonalLight = wx.StaticBox(self, -1, TD.SCENE_DIRECTIONAL_LIGHT)
        sizerDirectionalLight = wx.StaticBoxSizer(sbDirectonalLight, wx.VERTICAL)
        
        # Directional light diffuse color.
        static = wx.StaticText(self, -1, TD.DIRECTIONAL_LIGHT_DIFFUSE_COLOR)
        self._directionDiffuseColorButton = wxColorPickButton(self, -1, '')
        sizerDirectionalDiffuseColor = wx.BoxSizer(wx.HORIZONTAL)
        sizerDirectionalDiffuseColor.Add(static, 0, wx.CENTER, border = 5)
        sizerDirectionalDiffuseColor.Add(self._directionDiffuseColorButton, 0, wx.CENTER, border = 5)

        # Directional light specular color.
        static = wx.StaticText(self, -1, TD.DIRECTIONAL_LIGHT_SPECULAR_COLOR)
        self._directionSpecularColorButton = wxColorPickButton(self, -1, '')
        sizerDirectionalSpecularColor = wx.BoxSizer(wx.HORIZONTAL)
        sizerDirectionalSpecularColor.Add(static, 0, wx.CENTER, border = 5)
        sizerDirectionalSpecularColor.Add(self._directionSpecularColorButton, 0, wx.CENTER, border = 5)
        
        # Directional light brightness.
        static = wx.StaticText(self, -1, TD.LIGHT_BRIGHTESS)
        self._editDirectionLightBrightess = wx.TextCtrl(self, -1, '')
        sizerBrightness = wx.BoxSizer(wx.HORIZONTAL)
        sizerBrightness.Add(static, 0, wx.CENTER, border = 0)
        sizerBrightness.Add(self._editDirectionLightBrightess, 0, wx.CENTER, border = 0)
        
        # Direction of directonal light.
        static = wx.StaticText(self, -1, TD.DIRECTIONAL_LIGHT_DIRECTION)
        self._editDirection = wx.TextCtrl(self, -1)
        sizerDirectionalLightDirection = wx.BoxSizer(wx.HORIZONTAL)
        sizerDirectionalLightDirection.Add(static, 0, wx.CENTER, border = 5)
        sizerDirectionalLightDirection.Add(self._editDirection, 1, wx.ALL|wx.EXPAND, border = 5)
        
        sizerDirectionalLight.Add(sizerDirectionalDiffuseColor, 1, wx.EXPAND|wx.ALL, border = 5)
        sizerDirectionalLight.Add(sizerDirectionalSpecularColor, 1, wx.EXPAND|wx.ALL, border = 5)
        sizerDirectionalLight.Add(sizerBrightness, 1, wx.EXPAND|wx.ALL, border = 5)
        sizerDirectionalLight.Add(sizerDirectionalLightDirection, 1, wx.EXPAND|wx.ALL, border = 5)
        return sizerDirectionalLight
        
    def __CreateUIFog(self):
        sbFog = wx.StaticBox(self, -1, TD.SCENE_FOG)
        sizerFog = wx.StaticBoxSizer(sbFog, wx.VERTICAL)
        
        # enable.
        self._cbEnableFog = wx.CheckBox(self, -1, TD.ENABLE_FOG)
        
        # fog start
        static = wx.StaticText(self, -1, TD.FOG_START)
        self._editFogStart = wx.TextCtrl(self, -1)
        sizerFogStart = wx.BoxSizer(wx.HORIZONTAL)
        sizerFogStart.Add(static, 0, wx.CENTER, border = 5)
        sizerFogStart.Add(self._editFogStart, 1, wx.ALL|wx.EXPAND, border = 5)
        
        # fog end
        static = wx.StaticText(self, -1, TD.FOG_END)
        self._editFogEnd = wx.TextCtrl(self, -1)
        sizerFogEnd = wx.BoxSizer(wx.HORIZONTAL)
        sizerFogEnd.Add(static, 0, wx.CENTER, border = 5)
        sizerFogEnd.Add(self._editFogEnd, 1, wx.ALL|wx.EXPAND, border = 5)
        
        # fog color
        static = wx.StaticText(self, -1, TD.FOG_COLOR)
        self._fogColorButton = wxColorPickButton(self, -1, '')
        sizerFogColor = wx.BoxSizer(wx.HORIZONTAL)
        sizerFogColor.Add(static, 0, wx.CENTER, border = 5)
        sizerFogColor.Add(self._fogColorButton, 0, wx.CENTER, border = 5)
        
        sizerFog.Add(self._cbEnableFog, 0, wx.CENTER, border = 5)
        sizerFog.Add(sizerFogStart, 1, wx.EXPAND|wx.ALL, border= 5)
        sizerFog.Add(sizerFogEnd, 1, wx.EXPAND|wx.ALL, border= 5)
        sizerFog.Add(sizerFogColor, 1, wx.EXPAND|wx.ALL, border= 5)
        return sizerFog
        
    def UpdateUI(self):
        sceneHandle = SCENE_EDITOR._root.GetCoreHandle()
        
        self.__UpdateAmbientLightColor(sceneHandle)
        self.__UpdateAmbientLightBrightness(sceneHandle)
        self.__UpdateDirectionalLightDiffuse(sceneHandle)
        self.__UpdateDirectionalLightSpecular(sceneHandle)
        self.__UpdateDirectionalLightBrightness(sceneHandle)
        self.__UpdateDirectionalLightDirection(sceneHandle)
        self.__UpdateFogProperty()
        
    def __UpdateAmbientLightColor(self, sceneHandle):
        """ ambient light color """
        
        ambientHandle = Scene.GetAmbientLight(sceneHandle)
        r, g, b, a = LightAmbient.GetAmbient(ambientHandle)
        r, g, b, a = map(lambda n : int(n * 255.0), (r, g, b, a))
        self._ambientColorButton.SetValue(wx.Color(r, g, b, a))
        
    def __UpdateAmbientLightBrightness(self, sceneHandle):
        """ ambient light brightness """
        
        ambientHandle = Scene.GetAmbientLight(sceneHandle)
        brightness = LightAmbient.GetBrightness(ambientHandle)
        self._editAmbientBrightness.SetValue(str(brightness))
        
    def __UpdateDirectionalLightDiffuse(self, sceneHandle):
        """ directional light diffuse """
        
        directionHandle = Scene.GetDirectionLight(sceneHandle)
        r, g, b, a = LightDirection.GetDiffuse(directionHandle)
        r, g, b, a = map(lambda n : int(n * 255.0), (r, g, b, a))
        self._directionDiffuseColorButton.SetValue(wx.Color(r, g, b, a))
        
    def __UpdateDirectionalLightSpecular(self, sceneHandle):
        """ directional light specular """
        
        directionHandle = Scene.GetDirectionLight(sceneHandle)
        r, g, b, a = LightDirection.GetSpecular(directionHandle)
        r, g, b, a = map(lambda n : int(n * 255.0), (r, g, b, a))
        self._directionSpecularColorButton.SetValue(wx.Color(r, g, b, a))
        
    def __UpdateDirectionalLightBrightness(self, sceneHandle):
        """ directional light brightness """
        
        directionHandle = Scene.GetDirectionLight(sceneHandle)
        brightness = LightDirection.GetBrightness(directionHandle)
        self._editDirectionLightBrightess.SetValue(str(brightness))
        
    def __UpdateDirectionalLightDirection(self, sceneHandle):
        """ directional light direction """
        
        directionHandle = Scene.GetDirectionLight(sceneHandle)
        x, y, z = LightDirection.GetDirection(directionHandle)
        self._editDirection.SetValue(string.join([str(x), str(y), str(z)], ','))
    
    def __UpdateFogProperty(self):
        """ scene fog property """
        
        fogHandle = MaterialStatic.GetFogProperty()
        bEnable, fogStart, fogEnd, r, g, b, a = MPFog.GetFog(fogHandle)
        self._cbEnableFog.SetValue(bEnable)
        self._editFogStart.SetValue(str(fogStart))
        self._editFogEnd.SetValue(str(fogEnd))
        r, g, b, a = map(lambda n : int(n * 255.0), (r, g, b, a))
        self._fogColorButton.SetValue(wx.Color(r, g, b, a))
        
    def __OnAmbientColorChanged(self, e):
        sceneHandle = SCENE_EDITOR._root.GetCoreHandle()
        ambientHandle = Scene.GetAmbientLight(sceneHandle)        
        color = self._ambientColorButton.GetValue()
        r, g, b, a = map(lambda n : n / 255.0, (color.Red(), color.Green(), color.Blue(), color.Alpha()))
        LightAmbient.SetAmbient(ambientHandle, r, g, b, a)
        
    def __OnAmbientLightBrightnessChanged(self, e):
        sceneHandle = SCENE_EDITOR._root.GetCoreHandle()
        try:
            ambientHandle = Scene.GetAmbientLight(sceneHandle)
            brightness = float(self._editAmbientBrightness.GetValue())
            LightAmbient.SetBrightness(ambientHandle, brightness)
        except:
            self.__UpdateAmbientLightBrightness(sceneHandle)
        
    def __OnDirectionDiffuseColorChanged(self, e):
        sceneHandle = SCENE_EDITOR._root.GetCoreHandle()
        directionHandle = Scene.GetDirectionLight(sceneHandle)        
        color = self._directionDiffuseColorButton.GetValue()
        r, g, b, a = map(lambda n : n / 255.0, (color.Red(), color.Green(), color.Blue(), color.Alpha()))
        LightDirection.SetDiffuse(directionHandle, r, g, b, a)        
        
    def __OnDirectionSpecularColorChanged(self, e):
        sceneHandle = SCENE_EDITOR._root.GetCoreHandle()
        directionHandle = Scene.GetDirectionLight(sceneHandle)        
        color = self._directionSpecularColorButton.GetValue()
        r, g, b, a = map(lambda n : n / 255.0, (color.Red(), color.Green(), color.Blue(), color.Alpha()))
        LightDirection.SetSpecular(directionHandle, r, g, b, a)      
        
    def __OnDirectionalLightBrightnessChanged(self, e): 
        sceneHandle = SCENE_EDITOR._root.GetCoreHandle()
        try:
            directionalLightHandle = Scene.GetDirectionLight(sceneHandle)
            brightness = float(self._editDirectionLightBrightess.GetValue())
            LightDirection.SetBrightness(directionalLightHandle, brightness)
        except:
            self.__UpdateDirectionalLightBrightness(sceneHandle)
            
    def __OnDirectionalLightDirectionChanged(self, e):
        sceneHandle = SCENE_EDITOR._root.GetCoreHandle()
        try:
            directionalLightHandle = Scene.GetDirectionLight(sceneHandle)
            x, y, z = map(float, self._editDirectionalLightDireciton.GetValue().split(','))
            LightDirection.SetDirection(directionalLightHandle, x, y, z)
        except:
            self.__UpdateDirectionalLightDirection(sceneHandle)
        
    def __OnFogColorChanged(self, e):
        fogHandle = MaterialStatic.GetFogProperty()
        bEnable, fogStart, fogEnd, r, g, b, a = MPFog.GetFog(fogHandle)
        color = self._fogColorButton.GetValue()
        r, g, b, a = map(lambda n : n / 255.0, (color.Red(), color.Green(), color.Blue(), color.Alpha()))        
        MPFog.SetFog(fogHandle, bEnable, fogStart, fogEnd, r, g, b, a)        
        
    def __OnCbEnableFog(self, e):
        fogHandle = MaterialStatic.GetFogProperty()
        bEnable, fogStart, fogEnd, r, g, b, a = MPFog.GetFog(fogHandle)
        if e.IsChecked():
            bEnable = True
        else:
            bEnable = False
        MPFog.SetFog(fogHandle, bEnable, fogStart, fogEnd, r, g, b, a)
        
    def __OnFogStartChanged(self, e):
        fogHandle = MaterialStatic.GetFogProperty()
        bEnable, fogStart, fogEnd, r, g, b, a = MPFog.GetFog(fogHandle)
        try:
            fogStart = float(self._editFogStart.GetValue())
        except:
            return
            
        MPFog.SetFog(fogHandle, bEnable, fogStart, fogEnd, r, g, b, a)
        
    def __OnFogEndChanged(self, e):
        fogHandle = MaterialStatic.GetFogProperty()
        bEnable, fogStart, fogEnd, r, g, b, a = MPFog.GetFog(fogHandle)
        try:
            fogEnd = float(self._editFogEnd.GetValue())
        except:
            return
            
        MPFog.SetFog(fogHandle, bEnable, fogStart, fogEnd, r, g, b, a)               